<!-- 创建时间: 2021年09月26日 星期天 14:18 -->
<template>
    <div class="index_container">
        <el-row class="main_row">
            <el-col :span="12">
                <el-row class="main_row_childRow">
                    <el-col>
                        <el-card class="box-card"
                                 v-loading="searchLoading">
                            <div slot="header"
                                 class="clearfix">
                                <span class="el-icon-user-solid">{{ userName }}</span>
                                <el-button type="success"
                                           round
                                           @click="startSignIn"
                                           :disabled="startSignInBtnDisabled()">开始签到</el-button>
                            </div>
                            <el-row class="card_main">
                                <el-col class="el-icon-position essential"
                                        :xs="6"
                                        :sm="6"
                                        :md="6"
                                        :lg="4"
                                        :xl="3">签到班级</el-col>
                                <el-col :xs="18"
                                        :sm="18"
                                        :md="18"
                                        :lg="20"
                                        :xl="21">
                                    <el-select v-model="selectClass"
                                               clearable
                                               filterable
                                               placeholder="请输入后搜索"
                                               :disabled="timingTime != null"
                                               @blur="selectBlur"
                                               ref="selectClassFocus">
                                        <el-option v-for="(item, index) in classList"
                                                   :key="index"
                                                   :label="item.className"
                                                   :value="item.classNumber">
                                        </el-option>
                                    </el-select>
                                    <el-button icon="el-icon-search"
                                               circle
                                               title="搜索"
                                               :disabled="timingTime != null"
                                               @click="searchClassBtn"></el-button>
                                    <el-popover placement="top"
                                                width="200"
                                                trigger="click"
                                                content="输入班级部分或全部名称，点击搜索按钮，可查询相关班级。不可直接输入！">
                                        <i class="el-icon-question"
                                           slot="reference"
                                           style="color: darkgrey; cursor: pointer"></i>
                                    </el-popover>
                                </el-col>
                            </el-row>
                            <el-row class="card_main">
                                <el-col class="el-icon-timer essential"
                                        :xs="6"
                                        :sm="6"
                                        :md="6"
                                        :lg="4"
                                        :xl="3">签到计时</el-col>
                                <el-col :xs="18"
                                        :sm="18"
                                        :md="18"
                                        :lg="20"
                                        :xl="21">
                                    <el-select v-model="setTime[2]"
                                               placeholder="请选择"
                                               :disabled="timingTime != null">
                                        <el-option v-for="item in minInfo.list"
                                                   :key="item"
                                                   :label="item"
                                                   :value="item">
                                        </el-option>
                                    </el-select>&nbsp;&nbsp;分&nbsp;&nbsp;
                                    <el-select v-model="setTime[3]"
                                               placeholder="请选择"
                                               :disabled="timingTime != null">
                                        <el-option v-for="item in secInfo.list"
                                                   :key="item"
                                                   :label="item"
                                                   :value="item">
                                        </el-option>
                                    </el-select>&nbsp;&nbsp;秒
                                </el-col>
                            </el-row>
                            <el-row class="card_main">
                                <el-col class="el-icon-refresh essential"
                                        :xs="6"
                                        :sm="6"
                                        :md="6"
                                        :lg="4"
                                        :xl="3">刷新间隔</el-col>
                                <el-col :xs="18"
                                        :sm="18"
                                        :md="18"
                                        :lg="20"
                                        :xl="21">
                                    <el-select v-model="refreshInterval"
                                               placeholder="请选择"
                                               :disabled="timingTime != null">
                                        <el-option v-for="item in refreshIntervalList"
                                                   :key="item.value"
                                                   :label="item.label"
                                                   :value="item.value">
                                        </el-option>
                                    </el-select>
                                </el-col>
                            </el-row>
                            <el-row class="card_main">
                                <el-col class="el-icon-star-off"
                                        :xs="6"
                                        :sm="6"
                                        :md="6"
                                        :lg="4"
                                        :xl="3">课程名称</el-col>
                                <el-col :xs="18"
                                        :sm="18"
                                        :md="18"
                                        :lg="20"
                                        :xl="21">
                                    <el-row>
                                        <el-col :span="14">
                                            <div class="box">
                                                <div class="box_top">
                                                    <el-autocomplete class="inline-input"
                                                                     v-model="courseName"
                                                                     :disabled="timingTime != null"
                                                                     :fetch-suggestions="querySearchCourse"
                                                                     clearable
                                                                     :maxlength="20"
                                                                     :minlength="2"
                                                                     show-word-limit
                                                                     placeholder="请输入课程名称"
                                                                     @select="handleCourseSelect">
                                                    </el-autocomplete>
                                                    <el-popover placement="top"
                                                                width="200"
                                                                trigger="click"
                                                                content="默认为签到，用户可自定义。由于用户在某一班级同时授两们课(含)以上的签到情况而进行区分。">
                                                        <i class="el-icon-question"
                                                           slot="reference"
                                                           style="color: darkgrey; cursor: pointer"></i>
                                                    </el-popover>
                                                </div>
                                                <div class="box_bottom">
                                                    <span v-show="courseNameList.length != 0"
                                                          class="fa fa-hand-o-right"
                                                          style="color: darkgray; font-size: 10px">
                                                        共{{ courseNameList.length }}门课程
                                                    </span>
                                                </div>
                                            </div>
                                        </el-col>
                                        <el-col :span="10">
                                            <el-button type="danger"
                                                       style="float: right"
                                                       v-if="timingTime != null"
                                                       @click="endSignIn"
                                                       round>结束签到</el-button>
                                        </el-col>
                                    </el-row>
                                </el-col>
                            </el-row>
                        </el-card>
                    </el-col>
                    <el-col>
                        <count-down v-bind:timeControl="timeControl"
                                    v-bind:setTime="setTime"
                                    ref="child"></count-down>
                    </el-col>
                </el-row>
            </el-col>
            <el-col :span="12"
                    style="display: flex; justify-content: center; align-items: center">
                <el-image style="width: 600px; height: 600px"
                          v-if="signInImage != ''"
                          :src="signInImage"
                          fit="contain">
                    <div slot="placeholder"
                         class="image-slot">
                        加载中<span class="dot">...</span>
                    </div>
                </el-image>
                <el-tag v-if="signInImage == ''"
                        type="danger"
                        effect="plain">暂无签到码</el-tag>
            </el-col>
        </el-row>
    </div>
</template>

<script>
//这里可以导入其他文件（比如：组件，工具js，第三方插件js，json文件，图片文件等等）
//例如：import 《组件名称》 from '《组件路径》';
import countDown from './countDown/countDown.vue'
// https://www.jianshu.com/p/c75d9d2fbb8d
import setPromiseInterval, {
    clearPromiseInterval
} from 'set-promise-interval'
import {
    clear
} from 'localforage'

export default {
    //import引入的组件需要注入到对象中才能使用
    components: {
        countDown,
    },
    data () {
        //这里存放数据
        return {
            userName: '',
            userNumber: '',
            // -----------countDown子组件需要的东西-----------
            timeControl: [0, 0, 1, 1], //天，时，分，秒
            setTime: [0, 0, 5, 0], //天，时，分，秒
            // -----------countDown子组件需要的东西-----------
            // 时间选项列表 
            minInfo: {
                list: [],
            },
            secInfo: {
                list: [],
            },
            timingRequest: null,
            timingTime: null,
            // 班级选择所需变量
            classList: [],
            selectClass: '',
            searchClass: '',
            searchLoading: false,
            // 签到码图片
            signInImage: '',
            // 刷新间隔
            refreshIntervalList: [{
                value: -1,
                label: '本次签到有效',
            },
            {
                value: 5,
                label: '5秒',
            },
            {
                value: 10,
                label: '10秒',
            },
            ],
            refreshInterval: 5,
            // 课程名称
            courseName: '',
            // 课程名称选择列表
            courseNameList: [],
            // 签到码
            signInCode: '',
        }
    },
    //监听属性 类似于data概念
    computed: {},
    //监控data中的数据变化
    watch: {
        selectClass (val) {
            this.$http
                .post('queryClassSignInRecordCourseName', {
                    classNumber: val,
                    teacherNumber: this.userNumber,
                })
                .then((res) => {
                    this.courseNameList = res.body
                })
        },
    },
    beforeRouteLeave (to, from, next) {
        // 导航离开该组件的对应路由时调用
        // 可以访问组件实例 `this`
        localStorage.removeItem(this.$route.query.session)
        next()
    },
    methods: {
        // 课程名的输入查询建设列表     
        querySearchCourse (queryString, cb) {
            if (this.courseNameList.length == 0)
                cb([])
            var courseNameList = this.courseNameList.map((terminal) => {
                return {
                    value: terminal.courseName,
                }
            })
            var results = queryString ?
                courseNameList.filter(this.createFilter(queryString)) :
                courseNameList
            // 调用 callback 返回建议列表的数据
            cb(results)
        },
        createFilter (queryString) {
            return (courseNameList) => {
                return courseNameList.value
                    .toUpperCase()
                    .match(queryString.toUpperCase())
            }
        },
        // 处理课程选择
        handleCourseSelect (item) {
            console.log(item)
        },
        // 结束签到
        endSignIn () {
            clearInterval(this.timingTime)
            clearPromiseInterval(this.timingRequest)
            this.timingTime = null
            this.timingRequest = null
            this.signInImage = ''
            this.setTime = [0, 0, 5, 0]
            if (this.refreshInterval == -1) {
                this.$http.get('wx/endSignIn', {
                    params: {
                        signInCode: this.signInCode,
                    },
                })
            }
        },
        selectBlur (e) {
            this.searchClass = e.target.value
        },
        searchClassBtn () {
            this.searchLoading = true
            this.$http
                .post('searchClass', {
                    className: this.searchClass,
                    teacherNumber: this.userNumber,
                })
                .then((res) => {
                    this.searchLoading = false
                    if (res.data.length == 0) {
                        this.$message('暂无数据')
                        return
                    }
                    this.classList = res.data
                    this.$refs.selectClassFocus.focus()
                })
        },
        startSignInBtnDisabled () {
            if (this.setTime[0] == 0 &&
                this.setTime[1] == 0 &&
                this.setTime[2] == 0 &&
                this.setTime[3] == 0) {
                return true
            }
            if (this.timingTime != null) {
                return true
            }
            if (this.selectClass == '') {
                return true
            }
            if (this.courseName == '') {
                return true
            }
            return false
        },
        setMinSec () {
            this.minInfo.list = []
            this.secInfo.list = []
            for (let i = 0; i <= 59; i++) {
                this.minInfo.list.push(i)
                this.secInfo.list.push(i)
            }
        },
        /**
         * 开始签到按钮事件
         */
        startSignIn () {
            if (!this.checkStartSignInInfo()) {
                this.$message.error('签到信息不可为空')
                return
            }
            // 请求签到码
            let _this = this, signInTimeLen = null
            let siming = new Date()
            siming.setDate(siming.getDate() + this.setTime[0])
            siming.setHours(siming.getHours() + this.setTime[1])
            siming.setMinutes(siming.getMinutes() + this.setTime[2])
            siming.setSeconds(siming.getSeconds() + this.setTime[3] + 1)
            signInTimeLen =
                siming.getFullYear() +
                '-' +
                (siming.getMonth() + 1) +
                '-' +
                siming.getDate() +
                ' ' +
                siming.getHours() +
                ':' +
                siming.getMinutes() +
                ':' +
                siming.getSeconds()
            // console.log(signInTimeLen);return;
            if (this.refreshInterval > 0) {
                this.timingRequest = setPromiseInterval(() => {
                    if (this.setTime[3] <= this.refreshInterval &&
                        this.setTime[2] == 0 &&
                        this.setTime[1] == 0 &&
                        this.setTime[0] == 0) {
                        clearPromiseInterval(this.timingRequest)
                        return null
                    } else {
                        this.getQRCode(signInTimeLen)
                    }
                }, 1000 * this.refreshInterval)
            } else {
                this.getQRCode(signInTimeLen)
            }

            // 计时
            this.handleSetTime().then((res) => {
                if (res) {
                    _this.signInImage = ''
                }
            })
        },
        /**
         * 开始签到前信息验证
         */
        checkStartSignInInfo () {
            if (this.selectClass == '')
                return false
            if (this.courseName == '')
                return false
            let flag = true
            flag = this.refreshIntervalList.forEach((item, index) => {
                if (item.value == this.refreshInterval) {
                    return false
                }
            })
            if (flag)
                return false
            let settime = JSON.parse(JSON.stringify(this.setTime))
            settime.forEach((item, index) => {
                if (item == 0)
                    settime.splice(index, 1)
            })
            if (settime.length == 0)
                return false
            return true
        },
        /**
         * 获取签到码图片，方法抽取，因需要多次调用
         */

        async getQRCode (signInTimeLen) {
            let second = this.refreshInterval
            if (this.refreshInterval == -1) {
                let sum = this.setTime[0] * 24 * 60 * 60 +
                    this.setTime[1] * 60 * 60 +
                    this.setTime[2] * 60 +
                    this.setTime[3]
                second = sum
            }
            this.$http
                .post('wx/getQRCode', {
                    stuClass: this.selectClass,
                    second: second,
                    teacherNumber: this.userNumber,
                    signInTimeLen: signInTimeLen,
                    courseName: this.courseName, //课程名称
                })
                .then((res) => {
                    this.signInImage = res.body.data
                    this.signInCode = res.body.signInCode
                })
        },
        /**
         * 这个是倒计时的逻辑运算，需要根据业务进行处理
         */
        handleSetTime () {
            return new Promise((resolve) => {
                if (this.startSignInBtnDisabled())
                    resolve(false)
                let timeArr = this.setTime, obj = null
                let siming = new Date()
                siming.setDate(siming.getDate() + timeArr[0])
                siming.setHours(siming.getHours() + timeArr[1])
                siming.setMinutes(siming.getMinutes() + timeArr[2])
                siming.setSeconds(siming.getSeconds() + timeArr[3] + 1)
                this.timingTime = setInterval(() => {
                    obj = this.$refs.child.getTimeLeft(siming)
                    this.$set(this.setTime, 2, obj.minutes)
                    this.$set(this.setTime, 3, obj.seconds)
                    if (this.setTime[0] == 0 &&
                        this.setTime[1] == 0 &&
                        this.setTime[2] == 0 &&
                        this.setTime[3] == 0) {
                        clearInterval(this.timingTime)
                        this.timingTime = null
                        resolve(true)
                    }
                }, 1000)
            })
        },
        myEventSource () {
            let source = null

            // 用时间戳模拟登录用户
            const userId = new Date().getTime()

            console.log('userId:' + userId)

            if (!!window.EventSource) {
                // 建立连接
                source = new EventSource(this.$ROOT + '/sse/connect/' + userId)

                /**
                 * 连接一旦建立，就会触发open事件
                 * 另一种写法：source.onopen = function (event) {}
                 */
                source.onopen = (event) => {
                    console.log('建立链接...')
                }

                /**
                 * 客户端收到服务器发来的数据
                 * 另一种写法：source.onmessage = function (event) {}
                 */
                source.onmessage = (event) => {
                    console.log(event.data)
                }

                /**
                 * 如果发生通信错误（比如连接中断），就会触发error事件
                 * 或者：
                 * 另一种写法：source.onerror = function (event) {}
                 */
                source.onerror = (event) => {
                    if (event.readyState == EventSource.CLOSED) {
                        console.log('连接关闭')
                    } else {
                        console.log('error:', event)
                    }
                }
            } else {
                console.log('你的浏览器不支持SSE')
            }
        },
        // 关闭Sse连接
        closeMyEventSource (source) {
            source.close()
            const httpRequest = new XMLHttpRequest()
            httpRequest.open('GET', 'http://localhost:8080/sse/close/' + userId, true)
            httpRequest.send()
            console.log('close')
        },
    },
    //生命周期 - 创建完成（可以访问当前this实例）
    created () {
        let session = JSON.parse(localStorage.getItem(this.$route.query.session))
        this.userName = session.userName
        this.userNumber = session.userNumber
        this.setMinSec()
        this.myEventSource()
        // 监听窗口关闭事件，主动去关闭sse连接，如果服务端设置永不过期，浏览器关闭后手动清理服务端数据
        window.onbeforeunload = function () {
            this.closeMyEventSource()
        }
    },
    //生命周期 - 挂载完成（可以访问DOM元素）
    mounted () { },
    //当data中定义的数据有变化时就会加载updated方法
    updated () { },
}
</script>

<style lang="scss" scoped>
.index_container {
    padding: 10px;

    .main_row > div {
        padding: 10px;

        .main_row_childRow > div {
            margin-bottom: 15px;
        }
    }

    .el-header {
        display: flex;
        justify-content: center;
    }

    .clearfix {
        display: flex;
        justify-content: space-between;
        align-items: center;
    }

    .box-card {
        width: 100%;

        .card_main {
            display: flex;
            justify-content: center;
            align-items: center;
            margin-bottom: 10px;
        }
    }

    .el-card__header {
        padding: 15px;
    }
}
</style>
